﻿#define ENABLE_BORDERS

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using SibLib.GameComponents;
using SibLib.GameState;
using SibLib.Render;

namespace BricksBane.Screens
{
    sealed class HighscoreScreen : MenuScreen
    {      
        private Highscore[] m_Highscores;
        private int m_HighscoreCount;
        private int m_HighscoreRealCount;
        private string m_ModeName;
        private E_GameModes m_ModeCurrent;

        private ContentManager m_Content;
        private SpriteFont m_FontFixed;
#if ENABLE_BORDERS
        private PrimitiveBatch m_PrimitiveBatch;
#endif

        #region Initialization
        public HighscoreScreen() :
            base("Highscores")
        {
            m_Highscores = new Highscore[15];
            SelectMode(E_GameModes.Campaign);            
        }

        public override void LoadContent()
        {
            base.LoadContent();

            m_Content = new ContentManager(ScreenManager.Game.Services);

            m_FontFixed = m_Content.Load<SpriteFont>("Content/SpriteFontFixed");

#if ENABLE_BORDERS
            m_PrimitiveBatch = new PrimitiveBatch(ScreenManager.GraphicsDevice);
#endif
        }

        public override void UnloadContent()
        {
            base.UnloadContent();

            m_Content.Unload();
        }
        #endregion

        #region Update

        void MenuEntryBackSelected(object sender, PlayerIndexEventArgs e)
        {
            ExitScreen();
        }

        void SelectMode(E_GameModes mode)
        {
            m_ModeCurrent = mode;
            m_ModeName = m_ModeCurrent.ToString();      // TODO: well, would look nicer with const strings.
            m_MenuTitle = "Highscores - " + m_ModeName;
            m_HighscoreCount = HighscoreComponent.Instance.GetHighscores(m_Highscores);

            // TODO: proper filter (requires modification of HighscoreComponent).
            m_HighscoreRealCount = 0;
            for (int i = 0; i != m_HighscoreCount; i++)
            {
                if (m_Highscores[i].Message == m_ModeName)
                    m_HighscoreRealCount++;
            }
        }

        public override void HandleInput(GameTime gameTime, InputState input)
        {
            PlayerIndex playerIndex;
            if (input.IsMenuSelect(ControllingPlayer, out playerIndex) || 
                input.IsNewButtonPress(Buttons.DPadRight, ControllingPlayer.Value) || 
                input.IsNewButtonPress(Buttons.LeftThumbstickRight, ControllingPlayer.Value) ||
                input.IsNewButtonPress(Buttons.RightShoulder, ControllingPlayer.Value))
            {
                E_GameModes newMode = (E_GameModes)(((int)m_ModeCurrent + 1) % (int)E_GameModes.Count_);
                SelectMode(newMode);
            }

            if (input.IsNewButtonPress(Buttons.DPadLeft, ControllingPlayer.Value) ||
                input.IsNewButtonPress(Buttons.LeftThumbstickLeft, ControllingPlayer.Value) ||
                input.IsNewButtonPress(Buttons.LeftShoulder, ControllingPlayer.Value))
            {
                int newMode = (int)m_ModeCurrent - 1;
                if (newMode < 0)
                    newMode = (int)E_GameModes.Count_ - 1;
                SelectMode((E_GameModes)newMode);
            }
        }

        protected override void OnCancel(PlayerIndex playerIndex)
        {
            base.OnCancel(playerIndex);

            ExitScreen();
        }

        #endregion

        #region Render

        // Setup some strings beforehand, less garbage.
        private readonly string[] NUMBERS = { "#01", "#02", "#03", "#04", "#05", "#06", "#07", "#08", "#09", "#10", "#11", "#12", "#13", "#14", "#15" };
        private const int POS_BORDER_LEFT = 128;
        private const int POS_LINE_TOP_OFFSET = 1;
        private const int POS_NUM = 132;
        private const int POS_NAME = 220;
        private const int POS_SCORE = 800;
        private const int LINE_HEIGHT = 24;
        private readonly Vector2 LINE_SIZE = new Vector2(1024, LINE_HEIGHT);

        private const string PRESS_B = "Press B to exit";
        private const string NO_SCORE = "No score yet for this mode.";

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            SpriteFont font = ScreenManager.Font;

            Color color = new Color(Color.White, TransitionAlpha);

            spriteBatch.Begin();
            
            Vector2 bSize = font.MeasureString(PRESS_B);
            Vector2 bPos = new Vector2(1152.0f - bSize.X, 648.0f - bSize.Y);        // Reduced safe frame
            spriteBatch.DrawString(ScreenManager.Font, PRESS_B, bPos, color);

            if (m_HighscoreRealCount > 0)
            {
                int totalHeight = LINE_HEIGHT * m_HighscoreRealCount;

                float borderTop = ((720 - totalHeight) / 2.0f);

                Vector2 position = new Vector2(0.0f, borderTop + POS_LINE_TOP_OFFSET);
#if ENABLE_BORDERS
                Vector2 rectPos = new Vector2(POS_BORDER_LEFT, borderTop);
#endif

                int realIndex = 0;
                for (int i = 0; i != m_HighscoreCount; i++)
                {
                    if (m_Highscores[i].Message != m_ModeName)
                        continue;

                    position.X = POS_NUM;
                    spriteBatch.DrawString(m_FontFixed, NUMBERS[realIndex], position, color);
                    position.X = POS_NAME;
                    spriteBatch.DrawString(m_FontFixed, m_Highscores[i].Gamer, position, color);
                    position.X = POS_SCORE;
                    spriteBatch.DrawString(m_FontFixed, m_Highscores[i].Score.ToString(), position, color);         // TODO: this generates garbage, might not care.

#if ENABLE_BORDERS
                    m_PrimitiveBatch.DrawRectangle(rectPos, LINE_SIZE, color);
                    rectPos.Y += LINE_HEIGHT;
#endif
                    position.Y += LINE_HEIGHT;

                    realIndex++;
                }

#if ENABLE_BORDERS
                m_PrimitiveBatch.Begin(PrimitiveType.LineList);
                {
                    m_PrimitiveBatch.AddVertex(new Vector2(POS_NAME - 4, borderTop), color);
                    m_PrimitiveBatch.AddVertex(new Vector2(POS_NAME - 4, rectPos.Y), color);

                    m_PrimitiveBatch.AddVertex(new Vector2(POS_SCORE - 4, borderTop), color);
                    m_PrimitiveBatch.AddVertex(new Vector2(POS_SCORE - 4, rectPos.Y), color);
                }
                m_PrimitiveBatch.End();
#endif
            }
            else
            {
                Vector2 noPos = (new Vector2(1280.0f, 720.0f) - font.MeasureString(NO_SCORE)) / 2.0f;
                spriteBatch.DrawString(font, NO_SCORE, noPos, color);
            }

            spriteBatch.End();
        }
        #endregion
    }
}
